import { PlusOutlined,ExclamationCircleOutlined } from '@ant-design/icons'
import { Select,message } from 'antd'
import { useEffect, useMemo, useRef, useState } from 'react'
import './style/textareaWithParams.less'

function isIndexInBraces(s, index) {
  if (index < 0 || index >= s.length) {
    return false // 如果索引超出范围
  }

  const stack = [] // 用来存储 '{' 的索引
  const braceRanges = [] // 用来存储每对 '{}' 的范围

  // 遍历字符串，记录所有成对的 '{' 和 '}'
  for (let i = 0; i < s.length; i++) {
    if (s[i] === '{') {
      stack.push(i) // 遇到 '{'，压入栈
    } else if (s[i] === '}') {
      if (stack.length > 0) {
        // 栈不为空，找到一对括号
        const start = stack.pop()
        braceRanges.push([start, i]) // 记录括号范围
      }
    }
  }

  // 检查索引是否在任何括号范围内
  for (const [start, end] of braceRanges) {
    if (start < index && index < end) {
      return true
    }
  }

  return false
}

function insertNewLineAtCursor() {
  const selection = window.getSelection()
  if (!selection || selection.rangeCount === 0) return

  const range = selection.getRangeAt(0)

  // 创建一个文本节点，内容为换行符
  const textNode = document.createTextNode('\n\n')

  range.deleteContents()
  range.insertNode(textNode)
  // // 移动光标到换行符之后
  // range.setStartAfter(textNode)
  // range.setEndAfter(textNode)

  range.setStart(textNode, 1)
  range.collapse(true)

  selection.removeAllRanges()
  selection.addRange(range)
}

// 解析富文本内容为保存格式
function parseToValue(input) {
  // debugger
  const tempDiv = document.createElement('div')
  tempDiv.innerHTML = input
  // console.log('parseToValue>>>>>>>>>>>>>>>>>>', tempDiv.innerHTML)
  // 遍历子节点，将 <br> 转换为 \n，同时处理文本内容
  const traverseNodes = node => {
    let result = ''
    // debugger
    node.childNodes.forEach(child => {
      if (child.nodeName === 'BR') {
        result += '\n' // 换行符
      } else if (child.nodeType === Node.TEXT_NODE) {
        result += child.textContent // 文本内容
      } else if (child.nodeType === Node.ELEMENT_NODE) {
        if (child.nodeName === 'DIV') {
          result += '\n' // 换行符
        }
        result += traverseNodes(child) // 递归解析子元素
      }
    })
    return result
  }
  return traverseNodes(tempDiv)
}

// 使用正则表达式匹配{{}}包裹的内容， 更新文本内容为html内容
function replacePlaceholders(str) {
  return str.replace(
    /\{\{(.*?)\}\}/g,
    '<span class="textarea-badge" contentEditable="false"  onclick="event.stopPropagation(); event.preventDefault();">{{$1}}</span>'
  )
}
// 获取光标位置
function getCursorPosition(editableDiv) {
  // debugger
  let caretOffset = 0
  const doc = editableDiv.ownerDocument || editableDiv.document
  const win = doc.defaultView || doc.parentWindow
  const sel = win.getSelection()
  if (sel.rangeCount > 0) {
    const range = sel.getRangeAt(0)
    const preCaretRange = range.cloneRange()
    preCaretRange.selectNodeContents(editableDiv)
    preCaretRange.setEnd(range.endContainer, range.endOffset)
    caretOffset = preCaretRange.toString().length
  }
  return caretOffset
}
// 设置聚焦后的光标
function setCursorAtContentEditable(element, charIndex) {
  const range = document.createRange()
  const sel = window.getSelection()

  // 移除任何现有的选择
  sel.removeAllRanges()

  // 查找要插入光标的位置
  const childNodes = element.childNodes
  let node, offset

  for (let i = 0, sum = 0; i < childNodes.length; ++i) {
    node = childNodes[i]
    if (node.nodeType === Node.TEXT_NODE) {
      sum += node.textContent.length
      if (sum > charIndex) {
        offset = charIndex - (sum - node.textContent.length)
        break
      }
    }
  }

  if (!node) {
    // 如果没有找到合适的文本节点，则默认放置在最后
    node = element
    offset = charIndex
  }

  range.setStart(node, offset)
  range.collapse(true)

  // 添加范围到选择对象
  sel.addRange(range)
}
/**
 * 2024/12/26 start
 * 需求变更，不使用溯源节点信息，只是用节点本身输入变量
 */
export default function TextareaWithParamsV2({
  placeholder = '',
  value = '',
  error = false,
  children = null,
  onChange,
  citeOptions
}) {
  const { textareaRef, handleFocus, handleBlur } = usePlaceholder(placeholder)
  const valueRef = useRef(value || '')
  const selectVarRef = useRef(null)
  const [invalidVarsError, setInvalidVarsError] = useState('');

  const [showVarList, setShowVarList] = useState(false)
  const optionsMap = useMemo(() => {
      return citeOptions.reduce((acc, item) => {
        if (Array.isArray(item.options)) {
          item.options.forEach(option => {
            if (option?.value) {
              acc[option.value] = option.value;
            } 
          });
        }else {
          if (item?.value) {
            acc[item.value] = item.value;
          }
        }

        return acc;
     }, {})
  }, [citeOptions])
  
  /**
   * 2024/12/26 start
   * 需求变更，不使用溯源节点信息，只是用节点本身输入变量
   */
  const currentCursorPosition = useRef(1000)

  const setCurrentCursorPosition = index => {
    console.log('setCurrentCursorPosition', index)
    currentCursorPosition.current = index
  }
  const handleInput = () => {
    const value = parseToValue(textareaRef.current.innerHTML)
    valueRef.current = value
    onChange(value)
  }

  const getCurrentCursorPosition = () => {
    if (currentCursorPosition.current) {
      return currentCursorPosition.current
    }
    if (currentCursorPosition.current === 0) {
      return 0
    }
    return 1000
  }

  function handleInsertVariable(item, _option) {
    if (textareaRef.current && textareaRef.current.innerHTML.trim() === placeholder) {
      textareaRef.current.innerHTML = ''
      textareaRef.current.classList.remove('placeholder')
    }

    const position = getCurrentCursorPosition()
    const currentText = textareaRef.current.innerText
    
    // 计算实际插入位置
    let actualPosition = position
    const textBeforeCursor = currentText.slice(0, position)
    const ltCount = (textBeforeCursor.match(/</g) || []).length
    const gtCount = (textBeforeCursor.match(/>/g) || []).length
    actualPosition += (ltCount * 3) + (gtCount * 3) // 每个 < 变成 &lt; (+3), 每个 > 变成 &gt; (+3)

    const escapedText = currentText.replace(/</g, '&lt;').replace(/>/g, '&gt;')
    const newSpan = `{{${item}}}`
    let relPosition = actualPosition
    let leftText = escapedText.slice(0, relPosition)
    
    if (leftText.endsWith(`}`) && !leftText.endsWith('}}')) {
      relPosition += 1
      leftText = escapedText.slice(0, relPosition)
    }
    
    const newText = leftText + newSpan + escapedText.slice(relPosition)
    textareaRef.current.innerHTML = replacePlaceholders(newText)

    handleFocus()
    handleInput()
    setTimeout(() => {
      setShowVarList(false)
    }, 10)
  }

  function parseToHTML(input, validate = false) {
    // 先对 XML 内容进行转义
    const escapedInput = input.replace(/</g, '&lt;').replace(/>/g, '&gt;');
    
    let error = false
    const html = escapedInput
      .replace(/\{\{(.*?)\}\}/g, (a, part) => {
        if (validate) {
          error = optionsMap?.[part] === undefined
        }
        const msgZh = optionsMap?.[part] || part
        return `<span class=${
          error ? 'textarea-error' : 'textarea-badge'
        } contentEditable="false" onclick="event.stopPropagation(); event.preventDefault();">{{${msgZh}}}</span>`
      })
      .replace(/\n/g, '<br>')
    return [html, error]
  }

  // 删除第一个 useEffect
  useEffect(() => {
    textareaRef.current.innerHTML = parseToHTML(value || '', false)[0]
    handleBlur()
  }, [])

  // 添加检查变量引用的函数
  const checkVariableReferences = (text = '') => {
    if (!text) return [];
    const matches = text.match(/\{\{([^}]+)\}\}/g) || [];
    const uniqueVars = new Set(
      matches
        .map(match => match.slice(2, -2).trim())
        .filter(varName => !optionsMap[varName])
    );
    return Array.from(uniqueVars);
  }

  // 修改第二个 useEffect
  useEffect(() => {
    if (value !== valueRef.current) {
      textareaRef.current.innerHTML = parseToHTML(value || '', true)[0];
      valueRef.current = value;
    }
    // 检查当前值中的变量引用
    const invalidVars = checkVariableReferences(valueRef.current);
    if (invalidVars.length > 0) {
      console.warn('发现无效的变量引用:', invalidVars);
      setInvalidVarsError(`无效变量: ${invalidVars.join(', ')}`);
    } else {
      setInvalidVarsError('');
    }
  }, [value, citeOptions]);

  return (
    <div
      className={`text-area-with-params-container nodrag relative flex w-full flex-col rounded-md border text-sm shadow-sm ${
        error ? 'border-red-500' : 'border-input'
      }`}
    >
      <div
        className="flex items-center justify-between gap-1 border-b px-2 py-1"
        // onClick={() => textareaRef.current.focus()}
      >
        <span className="left-text-prompt">变量输入</span>
        <div className="flex gap-2">
          <Select
            ref={selectVarRef}
            open={showVarList}
            style={{ width: 144 }}
            onClick={() => {
              setShowVarList(true)
            }}
            onSelect={handleInsertVariable}
            onFocus={() => {
              setShowVarList(true)
            }}
            onBlur={() => {
              setShowVarList(false)
            }}
            suffixIcon={<PlusOutlined />}
            placement={'bottomRight'}
            className={'text-area-with-params-select'}
            popupClassName={'text-area-with-params-popup'}
            options={citeOptions}
          />
        </div>
      </div>
      <div
        ref={textareaRef}
        contentEditable
        style={{ height: 100 }}
        onInput={handleInput}
        onFocus={handleFocus}
        onBlur={e => {
          const currentPosition = getCursorPosition(textareaRef.current)
          const textContent = textareaRef.current.innerText
          // 检查光标位置是否在 {{}} 中
          if (!isIndexInBraces(textContent, currentPosition)) {
            handleBlur()
            setCurrentCursorPosition(currentPosition)
          }
        }}
        onKeyDown={e => {
          // 唤起插入变量
          if (e.key === '{') {
            console.log('唤起插入变量')

            const currentPosition = getCursorPosition(textareaRef.current)
            const textContent = textareaRef.current.innerText
            // 检查光标位置是否在 {{}} 中
            if (!isIndexInBraces(textContent, currentPosition)) {
              setShowVarList(true)
              if (selectVarRef) {
                setCurrentCursorPosition(currentPosition)
                selectVarRef.current.focus()
              }
            }
            e.preventDefault()
          }
          if (e.key === 'Enter') {
            console.log('输入回车')
            insertNewLineAtCursor()
            e.preventDefault()
          }
        }}
        className="nowheel panel-custom-richtext max-h-64 min-h-[80px] overflow-y-auto overflow-x-hidden whitespace-pre-wrap rounded-md border-none px-3 py-2 outline-none placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 dark:text-gray-50"
      ></div>
      {invalidVarsError && (
        <div className="px-3 py-1 text-xs text-red-500">
          <ExclamationCircleOutlined />
          {invalidVarsError}
        </div>
      )}
      {children}
    </div>
  )
}

function usePlaceholder(placeholder) {
  const divRef = useRef(null)

  const handleFocus = () => {
    if (divRef.current && divRef.current.innerHTML.trim() === placeholder) {
      divRef.current.innerHTML = ''
      divRef.current.classList.remove('placeholder')
    }
  }

  const handleBlur = () => {
    if (divRef.current && ['<br>', ''].includes(divRef.current.innerHTML.trim())) {
      divRef.current.innerHTML = placeholder
      divRef.current.classList.add('placeholder')
    }
  }

  useEffect(() => {
    if (!placeholder) return
    if (divRef.current) {
      // 添加事件监听
      divRef.current.addEventListener('focus', handleFocus)
      divRef.current.addEventListener('blur', handleBlur)

      // 清理事件监听
      return () => {
        if (divRef.current) {
          divRef.current.removeEventListener('focus', handleFocus)
          divRef.current.removeEventListener('blur', handleBlur)
        }
      }
    }
  }, [placeholder])

  return { textareaRef: divRef, handleFocus, handleBlur }
}
